home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume11 / templates / part03 < prev    next >
Encoding:
Internet Message Format  |  1987-10-04  |  46.3 KB

  1. Subject:  v11i093:  Template mode for GNU Emacs, Part03/06
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rs@uunet.UU.NET
  5.  
  6. Submitted-by: "Mark A. Ardis" <maa@sei.cmu.edu>
  7. Posting-number: Volume 11, Issue 93
  8. Archive-name: templates/part03
  9.  
  10. #! /bin/sh
  11. # This is a shell archive, meaning:
  12. # 1. Remove everything above the #! /bin/sh line.
  13. # 2. Save the resulting text in a file.
  14. # 3. Execute the file with /bin/sh (not csh) to create:
  15. #    tplhelper.el
  16. export PATH; PATH=/bin:/usr/bin:$PATH
  17. echo shar: "extracting 'tplhelper.el'" '(45072 characters)'
  18. if test -f 'tplhelper.el'
  19. then
  20.     echo shar: "will not over-write existing file 'tplhelper.el'"
  21. else
  22. sed 's/^X//' << \SHAR_EOF > 'tplhelper.el'
  23. X;;; tplhelper.el -- Helper functions for template-mode.
  24. X;;; Copyright (C) 1987 Mark A. Ardis.
  25. X
  26. X(provide 'tplhelper)
  27. X
  28. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  29. X
  30. X(defun tpl-blank-line ()
  31. X  "Returns t if current line contains only whitespace.
  32. X    Otherwise, returns nil."
  33. X                    ; Local Variables
  34. X  (let (result)
  35. X                    ; Body
  36. X    (save-excursion
  37. X      (beginning-of-line)
  38. X      (if (eolp)
  39. X      (setq result t)
  40. X    ; else
  41. X    (progn
  42. X      (re-search-forward tpl-pattern-whitespace (point-max) t)
  43. X      (if (eolp)
  44. X          (setq result t)
  45. X        (setq result nil)
  46. X        ) ; if
  47. X      ) ; progn
  48. X    ) ; if
  49. X      ) ; save
  50. X    ; return
  51. X    result
  52. X    ) ; let
  53. X  ) ; defun tpl-blank-line
  54. X
  55. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  56. X
  57. X(defun tpl-build-template-list ()
  58. X  "Build template-list, using current major mode."
  59. X                    ; Local Variables
  60. X  (let (mode-entry template-list)
  61. X                    ; Body
  62. X    (setq tpl-local-template-list
  63. X      (list (tpl-mode-templates
  64. X         (tpl-mode-match 'generic tpl-global-template-list))))
  65. X    ; Use loaded templates if available
  66. X    (setq template-list
  67. X      (tpl-mode-templates
  68. X       (tpl-mode-match major-mode tpl-global-template-list)))
  69. X    (if template-list
  70. X    (setq tpl-local-template-list
  71. X          (cons template-list tpl-local-template-list))
  72. X      ; else
  73. X      (progn
  74. X    (setq mode-entry (tpl-mode-match major-mode tpl-auto-template-alist))
  75. X    (if mode-entry
  76. X        (progn
  77. X          (load-tpl-library (tpl-mode-file mode-entry) major-mode)
  78. X          ) ; progn
  79. X      ; else
  80. X      (message "No templates found for this mode.")
  81. X      ) ; if mode-entry
  82. X    ) ; progn
  83. X      ) ; if template-list
  84. X    (if tpl-rebuild-all-templates-template
  85. X    (tpl-make-all-templates-template)
  86. X      ) ; if
  87. X    ) ; let
  88. X  ) ; defun tpl-build-template-list
  89. X
  90. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  91. X
  92. X(defun tpl-delete-placeholders-in-region (start stop)
  93. X  "Delete all placeholders in region between START and STOP."
  94. X                    ; Local Variables
  95. X  (let (stop-marker)
  96. X                    ; Body
  97. X    (setq stop-marker (make-marker))
  98. X    (set-marker stop-marker stop)
  99. X    (goto-char start)
  100. X    (while (re-search-forward tpl-pattern-placeholder
  101. X                  (marker-position stop-marker) t)
  102. X      (re-search-backward tpl-pattern-placeholder)
  103. X      (delete-placeholder)
  104. X      ) ; while
  105. X    (set-marker stop-marker nil)
  106. X    ) ; let
  107. X  ) ; defun tpl-delete-placeholders-in-region
  108. X
  109. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  110. X
  111. X(defun tpl-expand-lexical-type (name stop)
  112. X  "Expand the lexical placeholder NAME at point.  Replaces all instances
  113. X    of identical placeholders before STOP with the same value.
  114. X    Checks for match with lexical description."
  115. X                    ; Local Variables
  116. X  (let (save-hook)
  117. X                    ; Body
  118. X    (if (boundp 'sym-check-validity-hook)
  119. X    (setq save-hook sym-check-validity-hook)
  120. X      (setq save-hook nil)
  121. X      ) ; if
  122. X    (setq sym-check-validity-hook 'tpl-lexical-check)
  123. X    (setq tpl-lexical-pattern (tpl-find-value-of-template name))
  124. X    (if tpl-lexical-pattern
  125. X    (tpl-expand-text-type stop)
  126. X      (error "Cannot find template.")
  127. X      ) ; if
  128. X    (setq sym-check-validity-hook save-hook)
  129. X    ) ; let
  130. X  ) ; defun tpl-expand-lexical-type
  131. X
  132. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  133. X
  134. X(defun tpl-expand-placeholder (stop)
  135. X  "Expand the placeholder at point.  Replace identical occurrences
  136. X    of text placeholders before STOP with the same value."
  137. X                    ; Local Variables
  138. X  (let (placeholder template-name start placeholder-name)
  139. X                    ; Body
  140. X    (setq start (point))
  141. X                    ; Process placeholder
  142. X    (setq placeholder (tpl-scan-placeholder))
  143. X    (setq template-name (tpl-token-name placeholder))
  144. X    (setq placeholder-name (tpl-token-value placeholder))
  145. X    (cond
  146. X     ((equal template-name "text")
  147. X      (tpl-expand-text-type stop)
  148. X      ) ; (equal template-name "text")
  149. X     ((equal template-name "textenter")
  150. X      (tpl-expand-textenter-type stop)
  151. X      ) ; (equal template-name "textenter")
  152. X     ((equal template-name "textlong")
  153. X      (tpl-expand-textlong-type placeholder-name)
  154. X      ) ; (equal template-name "textlong")
  155. X     ((equal template-name tpl-destination-symbol)
  156. X      (progn
  157. X    (re-search-forward tpl-pattern-placeholder)
  158. X    (ding)
  159. X    (message "Cannot expand destination placeholder.")
  160. X    ) ; progn
  161. X      ) ; (equal template-name "textlong")
  162. X     (t
  163. X      (if (equal tpl-lexical-type
  164. X         (tpl-find-type-of-template template-name))
  165. X      (tpl-expand-lexical-type template-name stop)
  166. X    ; else
  167. X    (progn
  168. X      (re-search-forward tpl-pattern-placeholder)
  169. X      (delete-region start (point))
  170. X      (tpl-insert-template template-name)
  171. X      ) ; progn
  172. X    ) ; if
  173. X      ) ; t
  174. X     ) ; cond
  175. X    ) ; let
  176. X  ) ; defun tpl-expand-placeholder
  177. X
  178. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  179. X
  180. X(defun tpl-expand-text-type (stop)
  181. X  "Expand the text placeholder at point.  Replace identical placeholders
  182. X    before STOP with the same value.  Return that value."
  183. X                    ; Local Variables
  184. X  (let (start stop-marker placeholder-string sym-input)
  185. X                    ; Body
  186. X    (setq start (point))
  187. X    (if stop
  188. X    (progn
  189. X      (setq stop-marker (make-marker))
  190. X      (set-marker stop-marker stop)
  191. X      ) ; progn
  192. X      ) ; if stop
  193. X    (re-search-forward tpl-pattern-placeholder)
  194. X    (setq placeholder-string (buffer-substring start (point)))
  195. X    (goto-char start)
  196. X    (setq sym-input (sym-read-string
  197. X             (concat "Replace " placeholder-string " with what? ")
  198. X             placeholder-string))
  199. X    (if (= (length sym-input) 0)
  200. X    (re-search-forward placeholder-string)
  201. X      ; else
  202. X      (if stop
  203. X      (progn
  204. X        (setq start (point))
  205. X                    ; Replace all identical placeholders
  206. X        (while (re-search-forward placeholder-string
  207. X                      (marker-position stop-marker) t)
  208. X          (re-search-backward placeholder-string)
  209. X          (insert-before-markers sym-input)
  210. X          (delete-char (length placeholder-string))
  211. X          ) ; while (re-search-forward...)
  212. X        (goto-char start)
  213. X        ) ; progn
  214. X    ) ; if stop
  215. X      ) ; if (= (length sym-input) 0)
  216. X    ; return
  217. X    sym-input
  218. X    ) ; let
  219. X  ) ; defun tpl-expand-text-type
  220. X
  221. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  222. X
  223. X(defun tpl-expand-textenter-type (stop)
  224. X  "Expand the text placeholder at point.  Replace identical placeholders
  225. X    before STOP with the same value.  Enter that value in the symbol
  226. X    table."
  227. X                    ; Local Variables
  228. X  (let (value)
  229. X                    ; Body
  230. X    (setq value (tpl-expand-text-type stop))
  231. X    (sym-enter-id value)
  232. X    ) ; let
  233. X  ) ; defun tpl-expand-textenter-type
  234. X
  235. X
  236. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  237. X
  238. X(defun tpl-expand-textlong-type (name)
  239. X  "Expand the textlong placeholder at point called NAME."
  240. X                    ; Local Variables
  241. X  (let (start display-string save-buffer new-string start-column)
  242. X                    ; Body
  243. X                    ; Highlight placeholder
  244. X    (setq start (point))
  245. X    (re-search-forward tpl-pattern-placeholder)
  246. X    (delete-region start (point))
  247. X    (setq display-string (concat tpl-display-begin name tpl-display-end))
  248. X    (insert-before-markers display-string)
  249. X    (backward-char (length display-string))
  250. X                    ; Save current location
  251. X    (setq start (point))
  252. X                    ; Prepare buffer
  253. X    (save-window-excursion
  254. X      (setq save-buffer (buffer-name))
  255. X      (switch-to-buffer-other-window tpl-textlong-buffer)
  256. X      (erase-buffer)
  257. X      (shrink-window 5)
  258. X                    ; Wait for return from recursive edit
  259. X      (message (substitute-command-keys
  260. X        "Type replacement and exit with \\[exit-recursive-edit]"))
  261. X      (recursive-edit)
  262. X                    ; Get new value and insert
  263. X      (setq new-string (buffer-substring (point-min) (point-max)))
  264. X      (set-buffer save-buffer)
  265. X      (delete-windows-on tpl-textlong-buffer)
  266. X      ) ; save-window-excursion
  267. X    (bury-buffer tpl-textlong-buffer)
  268. X                    ; Return to proper location
  269. X    (goto-char start)
  270. X    (delete-char (length display-string))
  271. X    (setq start-column (current-column))
  272. X    (setq start (point))
  273. X    (insert-before-markers new-string)
  274. X    (indent-rigidly start (point) start-column)
  275. X    ) ; let
  276. X  ) ; defun tpl-expand-textlong-type
  277. X
  278. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  279. X
  280. X(defun tpl-find-end-of-group ()
  281. X  "Find the end of a group defined for query-replace-groups."
  282. X                    ; Local Variables
  283. X  (let ()
  284. X                    ; Body
  285. X    (if tpl-form-placeholder-name-from-context
  286. X    (tpl-make-placeholder-name)
  287. X      ) ; if tpl-form-placeholder-name-from-context
  288. X    (if tpl-include-prefix-in-groups
  289. X    (beginning-of-line nil)
  290. X      ) ; if tpl-include-prefix-in-groups
  291. X    (set-mark (point))
  292. X    (end-of-line nil)
  293. X    (re-search-forward tpl-end-group nil "not-t")
  294. X    (if tpl-verify-end-of-group
  295. X    (progn
  296. X      (message
  297. X       (concat "Position point AFTER end of group and exit ("
  298. X           (substitute-command-keys "\\[exit-recursive-edit]")
  299. X           ")."))
  300. X      (unwind-protect
  301. X          (recursive-edit)
  302. X        ) ; unwind-protect
  303. X      ) ; progn
  304. X      ) ; if tpl-verify-end-of-group
  305. X    (end-of-line 0)
  306. X    ) ; let
  307. X  ) ; defun tpl-find-end-of-group
  308. X
  309. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  310. X
  311. X(defun tpl-find-expansion-destination (start stop)
  312. X  "Delete special destination placeholder between START and STOP
  313. X    and set destination marker if a destination needs to be found."
  314. X                    ; Local Variables
  315. X  (let (stop-marker)
  316. X                    ; Body
  317. X    (goto-char start)
  318. X    (setq stop-marker (make-marker))
  319. X    (set-marker stop-marker stop)
  320. X    (while (re-search-forward tpl-destination-placeholder stop stop)
  321. X    (progn
  322. X      (re-search-backward tpl-pattern-placeholder)
  323. X      (delete-placeholder)
  324. X      (if tpl-destination-needed
  325. X          (progn
  326. X        (set-marker tpl-destination-marker (point))
  327. X        (setq tpl-destination-needed nil)
  328. X        ) ; progn
  329. X        ) ; if tpl-destination-needed
  330. X      ) ; progn
  331. X      ) ; while (re-search-forward tpl-destination-placeholder stop stop)
  332. X    (goto-char (marker-position stop-marker))
  333. X    (set-marker stop-marker nil)
  334. X    ) ; let
  335. X  ) ; defun tpl-find-expansion-destination
  336. X
  337. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  338. X
  339. X(defun tpl-find-next-group ()
  340. X  "Find the end of a group defined for query-replace-groups.
  341. X    Do not interact with user."
  342. X                    ; Local Variables
  343. X  (let ()
  344. X                    ; Body
  345. X    (end-of-line nil)
  346. X    (re-search-forward tpl-end-group nil "not-t")
  347. X    (end-of-line 0)
  348. X    ) ; let
  349. X  ) ; defun tpl-find-next-group
  350. X
  351. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  352. X
  353. X(defun tpl-find-template-file (file)
  354. X  "Find FILE using the 'tpl-load-path value."
  355. X                    ; Local Variables
  356. X  (let (tpl-name compiled-name dir-list looking)
  357. X                    ; Body
  358. X    (setq tpl-name (concat file ".tpl"))
  359. X    (setq compiled-name (concat file "tpl.elc"))
  360. X    (setq name nil)
  361. X    (setq looking t)
  362. X                    ; First try compiled versions
  363. X    (setq dir-list tpl-load-path)
  364. X    (while (and looking dir-list)
  365. X      (setq name (concat (car dir-list) "/" compiled-name))
  366. X      (setq dir-list (cdr dir-list))
  367. X      (if (file-readable-p name)
  368. X      (setq looking nil)
  369. X    ) ; if
  370. X      ) ; while
  371. X                    ; Second, try uncompiled
  372. X    (setq dir-list tpl-load-path)
  373. X    (while (and looking dir-list)
  374. X      (setq name (concat (car dir-list) "/" tpl-name))
  375. X      (setq dir-list (cdr dir-list))
  376. X      (if (file-readable-p name)
  377. X      (setq looking nil)
  378. X    ) ; if
  379. X      ) ; while
  380. X                    ; Last, try literal name
  381. X    (setq dir-list tpl-load-path)
  382. X    (while (and looking dir-list)
  383. X      (setq name (concat (car dir-list) "/" file))
  384. X      (setq dir-list (cdr dir-list))
  385. X      (if (file-readable-p name)
  386. X      (setq looking nil)
  387. X    ) ; if
  388. X      ) ; while
  389. X    ; return
  390. X    name
  391. X    ) ; let
  392. X  ) ; defun tpl-find-template-file
  393. X
  394. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  395. X
  396. X(defun tpl-find-template (tpl-name)
  397. X  "Find template TPL_NAME and return template or nil (if not found)."
  398. X                    ; Local Variables
  399. X  (let (found file-list template-file template-list template template-name)
  400. X                    ; Body
  401. X    (setq found nil)
  402. X    (setq file-list tpl-local-template-list)
  403. X    (while (and file-list (not found))
  404. X      (setq template-file (car file-list))
  405. X      (setq file-list (cdr file-list))
  406. X      (setq template-list (nth 1 template-file))
  407. X      (while (and template-list (not found))
  408. X    (setq template (car template-list))
  409. X    (setq template-list (cdr template-list))
  410. X    (setq template-name (tpl-token-name template))
  411. X    (if (equal template-name tpl-name)
  412. X        (setq found template)
  413. X      ) ; if (equal template-name tpl-name)
  414. X    ) ; while (and template-list (not found))
  415. X      ) ; while (and file-list (not found))
  416. X                    ; return
  417. X    found
  418. X    ) ; let
  419. X  ) ; defun tpl-find-template
  420. X
  421. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  422. X
  423. X(defun tpl-find-type-of-template (name)
  424. X  "Find template NAME and return its type or nil (if not found)."
  425. X                    ; Local Variables
  426. X  (let (template result)
  427. X                    ; Body
  428. X    (setq template (tpl-find-template name))
  429. X    (if template
  430. X    (setq result (tpl-token-type template))
  431. X      (setq result nil)
  432. X      ) ; if
  433. X                    ; return
  434. X    result
  435. X    ) ; let
  436. X  ) ; defun tpl-find-type-of-template
  437. X
  438. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  439. X
  440. X(defun tpl-find-value-of-template (name)
  441. X  "Find template NAME and return its value or nil (if not found)."
  442. X                    ; Local Variables
  443. X  (let (template result)
  444. X                    ; Body
  445. X    (setq template (tpl-find-template name))
  446. X    (if template
  447. X    (setq result (tpl-token-value template))
  448. X      (setq result nil)
  449. X      ) ; if
  450. X                    ; return
  451. X    result
  452. X    ) ; let
  453. X  ) ; defun tpl-find-value-of-template
  454. X
  455. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  456. X
  457. X(defun tpl-find-wrappers (tpl-name)
  458. X  "Find the beginning and ending part of TPL-NAME that encloses a
  459. X    destination placeholder."
  460. X                    ; Local Variables
  461. X  (let (msg template midpoint result)
  462. X                    ; Body
  463. X    (setq msg nil)
  464. X    (setq template (tpl-find-template tpl-name))
  465. X    (save-excursion
  466. X      (set-buffer tpl-work-buffer)
  467. X      (erase-buffer)
  468. X      (if template
  469. X      (progn
  470. X        (tpl-unscan template)
  471. X        (goto-char (point-min))
  472. X        (if (re-search-forward tpl-destination-placeholder
  473. X                   (point-max) t)
  474. X        (progn
  475. X          (delete-region (match-beginning 0) (match-end 0))
  476. X          (setq midpoint (point))
  477. X          ) ; progn
  478. X          ; else
  479. X          (progn
  480. X        (setq msg "Template does not contain a destination placeholder.")
  481. X        ) ; progn
  482. X          ) ; if
  483. X        ) ; progn
  484. X    ; else
  485. X    (progn
  486. X      (setq msg "Cannot find template.")
  487. X      ) ; progn
  488. X    ) ; if template
  489. X      (if (not msg)
  490. X      (setq result (list (buffer-substring 1 midpoint)
  491. X                 (buffer-substring midpoint (point-max))
  492. X                 (current-column)))
  493. X    ) ; if
  494. X      ) ; save-excursion
  495. X    (bury-buffer tpl-work-buffer)
  496. X    (if msg
  497. X    (error msg)
  498. X      ) ; if
  499. X                    ; return
  500. X    result
  501. X    ) ; let
  502. X  ) ; defun tpl-find-wrappers
  503. X
  504. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  505. X
  506. X(defun tpl-generate (tpl-name)
  507. X  "Insert and expand the template TPL-NAME at point."
  508. X                    ; Local Variables
  509. X  (let (start stop)
  510. X                    ; Body
  511. X    ; Insert and expand template
  512. X    (setq start (point))
  513. X    (insert-before-markers tpl-begin-placeholder tpl-name tpl-end-placeholder)
  514. X    (goto-char start)
  515. X    (setq tpl-destination-needed t)
  516. X    (message "Looking for template...")
  517. X    (tpl-expand-placeholder nil)
  518. X    (setq stop (point))
  519. X    (if (not tpl-destination-needed)
  520. X    (progn
  521. X      (goto-char (marker-position tpl-destination-marker))
  522. X      (set-marker tpl-destination-marker nil)
  523. X      ) ; progn
  524. X      ; else
  525. X      (progn
  526. X    (setq tpl-destination-needed nil)
  527. X    (goto-char start)
  528. X    (if (re-search-forward tpl-pattern-placeholder stop stop)
  529. X        (re-search-backward tpl-pattern-placeholder)
  530. X      ) ; if
  531. X    ) ; progn
  532. X      ) ; if (not tpl-destination-needed)
  533. X    (message "%s" "Done.")
  534. X    ) ; let
  535. X  ) ; defun tpl-generate
  536. X
  537. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  538. X
  539. X(defun tpl-get-placeholder-name ()
  540. X  "Prompt for a placeholder name.  If none supplied, use temporary
  541. X    name and regenerate another unique name.  Return the name."
  542. X                    ; Local Variables
  543. X  (let (name)
  544. X                    ; Body
  545. X    (if tpl-query-flag
  546. X    (progn
  547. X      (setq name (read-string
  548. X              (concat "Template name? ("
  549. X                  tpl-next-placeholder-name ") ")))
  550. X      ) ; progn
  551. X      ; else
  552. X      (setq name "")
  553. X      ) ; if tpl-query-flag
  554. X    (if (equal name "")
  555. X    (progn
  556. X      (setq name tpl-next-placeholder-name)
  557. X      (tpl-increment-next-placeholder-name)
  558. X      ) ; progn
  559. X      ) ; if (equal name "")
  560. X                    ; return
  561. X    name
  562. X    ) ; let
  563. X  ) ; tpl-get-placeholder-name
  564. X
  565. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  566. X
  567. X(defun tpl-increment-next-placeholder-name ()
  568. X  "Increment unique name for temporary placeholders."
  569. X                    ; Local Variables
  570. X  (let ()
  571. X                    ; Body
  572. X    (setq tpl-next-placeholder-number
  573. X      (1+ tpl-next-placeholder-number))
  574. X    (setq tpl-next-placeholder-name
  575. X      (concat tpl-temporary-placeholder-name
  576. X          tpl-next-placeholder-number))
  577. X    ) ; let
  578. X  ) ; defun tpl-increment-next-placeholder-name
  579. X
  580. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  581. X
  582. X(defun tpl-initialize-modes ()
  583. X  "Create initial Alist of major modes and their associated template files.
  584. X    Calls 'template-mode-load-hook' if it is defined."
  585. X                    ; Local Variables
  586. X  (let ()
  587. X                    ; Body
  588. X    (or (assq 'template-mode minor-mode-alist)
  589. X    (setq minor-mode-alist
  590. X          (cons '(template-mode " Template") minor-mode-alist)))
  591. X    (setq tpl-auto-template-alist
  592. X      (list
  593. X       (tpl-make-mode-entry 'awk-mode "awk")
  594. X       (tpl-make-mode-entry 'bib-mode "bib")
  595. X       (tpl-make-mode-entry 'c-mode "c")
  596. X       (tpl-make-mode-entry 'emacs-lisp-mode "elisp")
  597. X       (tpl-make-mode-entry 'generic "generic")
  598. X       (tpl-make-mode-entry 'LaTeX-mode "latex")
  599. X                    ; Should have another set of templates
  600. X                    ;   for Lisp
  601. X       (tpl-make-mode-entry 'lisp-mode "elisp")
  602. X       (tpl-make-mode-entry 'pascal-mode "pascal")
  603. X       (tpl-make-mode-entry 'scribe-mode "scribe")
  604. X       (tpl-make-mode-entry 'texinfo-mode "texinfo")
  605. X                    ; Should have another set of templates
  606. X                    ;    for TeX
  607. X       (tpl-make-mode-entry 'plain-TeX-mode "latex")
  608. X        ))
  609. X    (setq tpl-local-template-list nil)
  610. X    (get-buffer-create tpl-menu-buffer)
  611. X    (get-buffer-create tpl-textlong-buffer)
  612. X    (get-buffer-create tpl-work-buffer)
  613. X    (bury-buffer tpl-menu-buffer)
  614. X    (bury-buffer tpl-textlong-buffer)
  615. X    (bury-buffer tpl-work-buffer)
  616. X    (tpl-initialize-scan)
  617. X    (load-tpl-library "generic" 'generic)
  618. X    (and (boundp 'template-mode-load-hook)
  619. X     template-mode-load-hook
  620. X     (funcall template-mode-load-hook))
  621. X    ) ; let
  622. X  ) ; defun tpl-initialize-modes
  623. X
  624. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  625. X
  626. X(defun tpl-insert-function (template)
  627. X  "Insert a template at point using the function type TEMPLATE."
  628. X                    ; Local Variables
  629. X  (let (start stop-marker result save-depth)
  630. X                    ; Body
  631. X    (setq start (point))
  632. X    (setq stop-marker (make-marker))
  633. X    (insert (tpl-token-value template))
  634. X    (set-marker stop-marker (point))
  635. X                    ; Temporarily expand placeholders
  636. X                    ;    without asking
  637. X    (setq save-depth tpl-ask-expansion-depth)
  638. X    (setq tpl-ask-expansion-depth 10)
  639. X    (expand-placeholders-in-region start (point))
  640. X    (setq tpl-ask-expansion-depth save-depth)
  641. X                    ; Evaluate result
  642. X    (goto-char start)
  643. X    (save-excursion
  644. X      (setq result (eval (read (current-buffer))))
  645. X      ) ; save-excursion
  646. X                    ; Remove placeholder and insert result
  647. X    (delete-region start (marker-position stop-marker))
  648. X    (set-marker stop-marker nil)
  649. X    (insert result)
  650. X    ) ; let
  651. X  ) ; defun tpl-insert-function
  652. X
  653. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  654. X
  655. X(defun tpl-insert-repetition (template)
  656. X  "Insert at point instances of the repetition type TEMPLATE."
  657. X                    ; Local Variables
  658. X  (let (start template-name column)
  659. X                    ; Body
  660. X    (setq start (point))
  661. X    (setq column (current-column))
  662. X    (setq template-name (tpl-token-name template))
  663. X                    ; Insert first instance
  664. X    (tpl-unscan template)
  665. X    (re-search-backward tpl-pattern-placeholder)
  666. X    (delete-region start (point))
  667. X    (tpl-expand-placeholder nil)
  668. X                    ; Insert more instances
  669. X    (while (tpl-y-or-n-p (concat "More instances of " template-name "? "))
  670. X      (tpl-unscan template column)
  671. X      (cond
  672. X       ((> tpl-ask-expansion-depth 0)
  673. X    (progn
  674. X      (re-search-backward tpl-pattern-placeholder)
  675. X      (tpl-expand-placeholder nil)
  676. X      ) ; progn
  677. X    ) ; (> tpl-ask-expansion-depth 0)
  678. X       ) ; cond
  679. X      ) ; while (tpl-y-or-n-p...)
  680. X    ) ; let
  681. X  ) ; defun tpl-insert-repetition
  682. X
  683. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  684. X
  685. X(defun tpl-insert-selection (template)
  686. X  "Insert a template at point using the selection type TEMPLATE."
  687. X                    ; Local Variables
  688. X  (let (save-buffer start stop size choice choice-template choice-list
  689. X            display-string)
  690. X                    ; Body
  691. X                    ; Highlight placeholder
  692. X    (setq display-string (concat
  693. X              tpl-display-begin
  694. X              (tpl-token-name template)
  695. X              tpl-display-end))
  696. X    (insert-before-markers display-string)
  697. X    (backward-char (length display-string))
  698. X                    ; Prepare menu buffer
  699. X    (save-window-excursion
  700. X      (setq save-buffer (buffer-name))
  701. X      (switch-to-buffer-other-window tpl-menu-buffer)
  702. X      (erase-buffer)
  703. X                    ; Build the menu
  704. X      (tpl-unscan template)
  705. X                    ; Size the window
  706. X      (goto-char (point-max))
  707. X      (setq stop (point))
  708. X      (goto-char (point-min))
  709. X      (setq start (point))
  710. X      (setq size (1+ (count-lines start stop)))
  711. X      (setq size (max size window-min-height))
  712. X      (if (< size (window-height))
  713. X      (shrink-window (- (window-height) size))
  714. X    ) ; if
  715. X                    ; Allow user to view and select
  716. X      (setq choice (menu-mode))
  717. X      (set-buffer save-buffer)
  718. X      (delete-windows-on tpl-menu-buffer)
  719. X      ) ; save-window-excursion
  720. X    (bury-buffer tpl-menu-buffer)
  721. X    (delete-char (length display-string))
  722. X                    ; Insert choice as template or string
  723. X    (if choice
  724. X    (progn
  725. X      (setq choice-list (tpl-parse-choice choice))
  726. X      (setq choice-template (nth 1 choice-list))
  727. X      (if choice-template
  728. X          (tpl-insert-template choice-template)
  729. X        ; else
  730. X        (insert-before-markers (nth 0 choice-list))
  731. X        ) ; choice-template
  732. X      ) ; progn
  733. X      ; else insert placeholder
  734. X      (progn
  735. X    (setq display-string (concat tpl-begin-placeholder
  736. X                     (tpl-token-name template)
  737. X                     tpl-end-placeholder))
  738. X    (insert-before-markers display-string)
  739. X    (backward-char (length display-string))
  740. X    (error "Quit.")
  741. X    ) ; progn
  742. X      ) ; if choice
  743. X    ) ; let
  744. X  ) ; defun tpl-insert-selection
  745. X
  746. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  747. X
  748. X(defun tpl-insert-string-from-buffer (tpl-name display-string &optional buffer)
  749. X  "Insert a template at point using the string type TPL-NAME, temporarily
  750. X   represented by DISPLAY-STRING.  Optional third argument BUFFER is the
  751. X   buffer to search."
  752. X                    ; Local Variables
  753. X  (let (start string)
  754. X                    ; Body
  755. X    (if (not buffer)
  756. X    (setq buffer
  757. X          (read-buffer "tpl-insert-string: Template buffer? "
  758. X               tpl-new-template-buffer t))
  759. X      ) ; if
  760. X    (save-window-excursion
  761. X      (set-buffer buffer)
  762. X      (goto-char (point-min))
  763. X      (if (re-search-forward (concat tpl-begin-template-definition
  764. X                     " " tpl-name " ")
  765. X                 (point-max) t)
  766. X      (progn
  767. X        (re-search-forward tpl-begin-template-body)
  768. X        (beginning-of-line 2)
  769. X        (setq start (point))
  770. X        (re-search-forward tpl-end-template-body)
  771. X        (end-of-line 0)
  772. X        (setq string (buffer-substring start (point)))
  773. X        ) ; progn
  774. X    ; else
  775. X    (error "Could not find template in %s" buffer)
  776. X    ) ; if
  777. X      ) ; save-window-excursion
  778. X    (delete-char (length display-string))
  779. X    (insert-before-markers string)
  780. X    ) ; let
  781. X  ) ; defun tpl-insert-string-from-buffer
  782. X
  783. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  784. X
  785. X(defun tpl-insert-template (tpl-name)
  786. X  "Insert the template TPL-NAME at point."
  787. X                    ; Local Variables
  788. X  (let (display-string template start template-type looking)
  789. X                    ; Body
  790. X                    ; Display selected template
  791. X    (setq display-string (concat tpl-display-begin tpl-name tpl-display-end))
  792. X    (insert-before-markers display-string)
  793. X    (backward-char (length display-string))
  794. X    (setq looking t)
  795. X    (while looking
  796. X                    ; Find template.
  797. X      (setq template (tpl-find-template tpl-name))
  798. X      (if template
  799. X      (progn
  800. X        (setq looking nil)
  801. X                    ; Insert template
  802. X        (delete-char (length display-string))
  803. X        (setq start (point))
  804. X        (setq template-type (tpl-token-type template))
  805. X        (cond
  806. X         ((equal template-type tpl-sequence-type)
  807. X          (progn
  808. X        (tpl-unscan template)
  809. X        (tpl-find-expansion-destination start (point))
  810. X        (cond
  811. X         ((< tpl-ask-expansion-depth 0)
  812. X          (tpl-delete-placeholders-in-region start (point))
  813. X          ) ; (< tpl-ask-expansion-depth 0)
  814. X         ((> tpl-ask-expansion-depth 0)
  815. X          (progn
  816. X            (expand-placeholders-in-region start (point))
  817. X            ) ; progn
  818. X          ) ; (> tpl-ask-expansion-depth 0)
  819. X         ) ; cond
  820. X        ) ; progn
  821. X          ) ; (equal template-type tpl-sequence-type)
  822. X         ((equal template-type tpl-selection-type)
  823. X          (progn
  824. X        (tpl-insert-selection template)
  825. X        ) ; progn
  826. X          ) ; (equal template-type tpl-selection-type)
  827. X         ((equal template-type tpl-repetition-type)
  828. X          (progn
  829. X        (tpl-insert-repetition template)
  830. X        ) ; progn
  831. X          ) ; (equal template-type tpl-repetition-type)
  832. X         ((equal template-type tpl-function-type)
  833. X          (progn
  834. X        (tpl-insert-function template)
  835. X        ) ; progn
  836. X          ) ; (equal template-type tpl-function-type)
  837. X         ((equal template-type tpl-string-type)
  838. X          (progn
  839. X        (tpl-unscan template)
  840. X        ) ; progn
  841. X          ) ; (equal template-type tpl-string-type)
  842. X         ) ; cond
  843. X        ) ; progn
  844. X                    ; Else report failure
  845. X    (progn
  846. X      (if (y-or-n-p "Cannot find template---look in a buffer? ")
  847. X          (progn
  848. X        (setq looking nil)
  849. X        (tpl-insert-string-from-buffer tpl-name display-string)
  850. X        ) ; progn
  851. X        ; else
  852. X        (if (y-or-n-p "Cannot find template---load a template file? ")
  853. X        (progn
  854. X          (save-some-buffers)
  855. X          (load-tpl-file)
  856. X          ) ; progn
  857. X          ; else
  858. X          (progn
  859. X        (setq looking nil)
  860. X        (error "Gave up looking for template.")
  861. X        ) ; progn
  862. X          ) ; if (y-or-n-p ...load...)
  863. X        ) ; if (y-or-n-p ...look...)
  864. X      ) ; progn
  865. X    ) ; if template
  866. X      ) ; while looking
  867. X    ) ; let
  868. X  ) ; defun tpl-insert-template
  869. X
  870. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  871. X
  872. X(defun tpl-lexical-check (input)
  873. X  "Check INPUT for validity against lexical definition."
  874. X                    ; Local Variables
  875. X  (let (result)
  876. X                    ; Body
  877. X    (if (and (string-match tpl-lexical-pattern input)
  878. X         (equal (match-beginning 0) 0)
  879. X         (equal (match-end 0) (length input)))
  880. X    (setq result t)
  881. X      (setq result nil)
  882. X      ) ; if
  883. X    (if (not result)
  884. X    (progn
  885. X      (ding)
  886. X      (message (concat "String does not match pattern: "
  887. X               tpl-lexical-pattern))
  888. X      ) ; progn
  889. X      ) ; if
  890. X                    ; return
  891. X    result
  892. X    ) ; let
  893. X  ) ; defun tpl-lexical-check
  894. X
  895. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  896. X
  897. X(defun tpl-make-all-templates-template ()
  898. X  "Make a template consisting of a selection of all templates.
  899. X    Replace existing version if present."
  900. X                    ; Local Variables
  901. X  (let (name template-tree template-file template-list file-name name-list
  902. X         new-template-list)
  903. X                    ; Body
  904. X    (message "Rebuilding list of all templates...")
  905. X                    ; Build name-list
  906. X    (setq template-list tpl-local-template-list)
  907. X    (setq new-template-list nil)
  908. X    (setq name-list nil)
  909. X    (while template-list
  910. X      (setq template-file (car template-list))
  911. X      (setq template-list (cdr template-list))
  912. X      (setq file-name (nth 0 template-file))
  913. X                    ; Remove existing version if present
  914. X      (if (not (string-equal file-name tpl-all-templates-file))
  915. X      (progn
  916. X        (setq new-template-list
  917. X          (append new-template-list (list template-file)))
  918. X        (setq name-list
  919. X          (append name-list (nth 2 template-file)))
  920. X        ) ; progn
  921. X    ) ; if
  922. X      ) ; while template-list
  923. X                    ; Build template
  924. X    (save-window-excursion
  925. X      (set-buffer tpl-work-buffer)
  926. X      (erase-buffer)
  927. X      (while name-list
  928. X    (setq name (car name-list))
  929. X    (setq name-list (cdr name-list))
  930. X    (insert (car name) ":")
  931. X    (newline)
  932. X    ) ; while name-list
  933. X      (shell-command-on-region (point-min) (point-max) "sort -u" t)
  934. X                    ; Insert preface
  935. X      (goto-char (point-min))
  936. X      (insert tpl-begin-template-definition " "
  937. X          tpl-all-templates-name " "
  938. X          tpl-selection-type)
  939. X      (newline)
  940. X      (beginning-of-line 0)
  941. X      (delete-char 1)            ; Remove regular exression anchor
  942. X      (end-of-line)
  943. X      (newline)
  944. X      (insert tpl-begin-template-body)
  945. X      (beginning-of-line)
  946. X      (delete-char 1)            ; Remove regular exression anchor
  947. X                    ; Insert suffix
  948. X      (goto-char (point-max))
  949. X      (insert tpl-end-template-body)
  950. X      (beginning-of-line)
  951. X      (delete-char 1)
  952. X      (end-of-line)
  953. X      (newline)
  954. X                    ; Create template
  955. X      (goto-char (point-min))
  956. X      (setq template-tree (tpl-scan-template))
  957. X      ) ; save-window-excursion
  958. X    (bury-buffer tpl-work-buffer)
  959. X                    ; Rebuild template-list
  960. X    (setq tpl-local-template-list
  961. X      (append (list (list tpl-all-templates-file
  962. X                  (list template-tree) nil))
  963. X          new-template-list))
  964. X    (setq tpl-all-templates-template-invalid nil)
  965. X    (message "Rebuilding list of all templates...Done.")
  966. X    ) ; let
  967. X  ) ; defun tpl-make-all-templates-template
  968. X
  969. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  970. X
  971. X(defun tpl-make-completion-list ()
  972. X  "Create a completion list of template names for prompting."
  973. X                    ; Local Variables
  974. X  (let (name completion-list file-list template-file name-list)
  975. X                    ; Body
  976. X    ; Build completion list
  977. X    (setq completion-list nil)
  978. X    (setq file-list tpl-local-template-list)
  979. X    (while file-list
  980. X      (setq template-file (car file-list))
  981. X      (setq file-list (cdr file-list))
  982. X      (setq name-list (nth 2 template-file))
  983. X      (setq completion-list (append completion-list name-list))
  984. X      ) ; while file-list
  985. X                    ; return
  986. X    completion-list
  987. X    ) ; let
  988. X  ) ; defun tpl-make-completion-list
  989. X
  990. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  991. X
  992. X(defun tpl-make-keymap ()
  993. X  "Make keymap for template-mode."
  994. X                    ; Local Variables
  995. X  (let ()
  996. X                    ; Body
  997. X    (setq tpl-saved-map (current-local-map))
  998. X    (if (not template-mode-map)
  999. X    (progn
  1000. X      (setq template-mode-map tpl-saved-map)
  1001. X      (define-key
  1002. X        template-mode-map "\^c\^t\t" 'expand-symbol)
  1003. X      (define-key
  1004. X        template-mode-map "\^c\^ta" 'add-symbol)
  1005. X      (define-key
  1006. X        template-mode-map "\^c\^te" 'expand-placeholder)
  1007. X      (define-key
  1008. X        template-mode-map "\^c\^tg" 'query-replace-groups)
  1009. X      (define-key
  1010. X        template-mode-map "\^c\^tl" 'query-replace-lines)
  1011. X      (define-key
  1012. X        template-mode-map "\^c\^tr" 'replace-line-with-placeholder)
  1013. X      (define-key
  1014. X        template-mode-map "\^c\^tt" 'generate-template)
  1015. X      (define-key
  1016. X        template-mode-map "\^c\^tu" 'unwrap-template-around-point)
  1017. X      (define-key
  1018. X        template-mode-map "\^c\^tw" 'wrap-template-around-word)
  1019. X      (define-key
  1020. X        template-mode-map "\^c\^tW" 'wrap-template-around-line)
  1021. X      (define-key
  1022. X        template-mode-map "\^c\^t\^e" 'expand-placeholders-in-region)
  1023. X      (define-key
  1024. X        template-mode-map "\^c\^t\^h" 'describe-template-mode)
  1025. X      (define-key
  1026. X        template-mode-map "\^c\^t\^k" 'delete-placeholder)
  1027. X      (define-key
  1028. X        template-mode-map "\^c\^t\^n" 'next-placeholder)
  1029. X      (define-key
  1030. X        template-mode-map "\^c\^t\^p" 'previous-placeholder)
  1031. X      (define-key
  1032. X        template-mode-map "\^c\^t\^r" 'replace-region-with-placeholder)
  1033. X      (define-key
  1034. X        template-mode-map "\^c\^t\^u" 'rewrap-template-around-point)
  1035. X      (define-key
  1036. X        template-mode-map "\^c\^t\^w" 'wrap-template-around-region)
  1037. X      (define-key
  1038. X        template-mode-map "\^c\^t?" 'generate-any-template)
  1039. X      ) ; progn
  1040. X      ) ; if
  1041. X    (use-local-map template-mode-map)
  1042. X    ) ; let
  1043. X  ) ; defun tpl-make-keymap
  1044. X
  1045. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1046. X
  1047. X(defun tpl-make-mode-entry (name file)
  1048. X  "Constructor for mode entries from NAME FILE."
  1049. X                    ; Local Variables
  1050. X  (let ()
  1051. X                    ; Body
  1052. X    (list (list 'name name) (list 'file file))
  1053. X    ) ; let
  1054. X  ) ; defun tpl-make-mode-entry
  1055. X
  1056. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1057. X
  1058. X(defun tpl-make-placeholder-name ()
  1059. X  "Create a name for a new template by searching for the first symbol
  1060. X    after point."
  1061. X                    ; Local Variables
  1062. X  (let ()
  1063. X                    ; Body
  1064. X    (save-excursion
  1065. X      (if (re-search-forward tpl-pattern-symbol nil t)
  1066. X      (progn
  1067. X        (setq tpl-formed-placeholder-name
  1068. X          (buffer-substring (match-beginning 0) (match-end 0)))
  1069. X        ) ; progn
  1070. X    ; else
  1071. X    (progn
  1072. X      (setq tpl-formed-placeholder-name tpl-next-placeholder-name)
  1073. X      (tpl-increment-next-placeholder-name)
  1074. X      ) ; progn
  1075. X    ) ; if
  1076. X      ) ; save-excursion
  1077. X    ) ; let
  1078. X  ) ; defun tpl-make-placeholder-name
  1079. X
  1080. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1081. X
  1082. X(defun tpl-make-template-entry (name templates)
  1083. X  "Constructor for mode entries from NAME TEMPLATES."
  1084. X                    ; Local Variables
  1085. X  (let ()
  1086. X                    ; Body
  1087. X    (list (list 'name name) (list 'templates templates))
  1088. X    ) ; let
  1089. X  ) ; defun tpl-make-template-entry
  1090. X
  1091. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1092. X
  1093. X(defun tpl-make-template-list (file &optional buffer)
  1094. X  "Create a template list from the templates in FILE.
  1095. X    Optional second argument non-nil means use a buffer, not a file."
  1096. X                    ; Local Variables
  1097. X  (let (template-list template-tree template-name
  1098. X              name-list msg table root-name)
  1099. X                    ; Body
  1100. X    (setq msg (concat "Loading templates in " file ": "))
  1101. X    (save-window-excursion
  1102. X      (setq table (syntax-table))
  1103. X      (set-buffer tpl-work-buffer)
  1104. X      (erase-buffer)
  1105. X      (if buffer
  1106. X      (insert-buffer file)
  1107. X    ; else
  1108. X    (insert-file file)
  1109. X    ) ;if buffer
  1110. X      (set-syntax-table table)
  1111. X      (goto-char (point-min))
  1112. X      (setq name-list nil)
  1113. X      (while (re-search-forward
  1114. X          tpl-begin-template-definition (point-max) t)
  1115. X    (beginning-of-line)
  1116. X    (setq template-tree (tpl-scan-template))
  1117. X    (setq template-list (append template-list (list template-tree)))
  1118. X    (setq template-name (tpl-token-name template-tree))
  1119. X    (message (concat msg template-name "..."))
  1120. X    (if (not (equal tpl-lexical-type
  1121. X            (tpl-token-type template-tree)))
  1122. X        (setq name-list
  1123. X          (append name-list (list (list template-name))))
  1124. X      ) ; if
  1125. X    ) ; while (re-search-forward...)
  1126. X      (setq template-list
  1127. X        (list (tpl-root-of-file-name (file-name-nondirectory file))
  1128. X          template-list name-list))
  1129. X      ) ; save-window-excursion
  1130. X    (bury-buffer tpl-work-buffer)
  1131. X    (message (concat msg "Done."))
  1132. X                    ; return
  1133. X    template-list
  1134. X    ) ; let
  1135. X  ) ; defun tpl-make-template-list
  1136. X
  1137. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1138. X
  1139. X(defun tpl-mode-file (mode-entry)
  1140. X  "Selector for file field of MODE-ENTRY."
  1141. X                    ; Local Variables
  1142. X  (let ()
  1143. X                    ; Body
  1144. X    (car (cdr (assq 'file mode-entry)))
  1145. X    ) ; let
  1146. X  ) ; defun tpl-mode-file
  1147. X
  1148. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1149. X
  1150. X(defun tpl-mode-match  (mode-nm list)
  1151. X  "Find mode-entry that matches MODE-NM in LIST."
  1152. X                    ; Local Variables
  1153. X  (let (entry)
  1154. X                    ; Body
  1155. X    (while list
  1156. X      (setq entry (car list))
  1157. X      (setq list (cdr list))
  1158. X      (if (equal (tpl-mode-name entry) mode-nm)
  1159. X      (setq list nil)
  1160. X    ; else
  1161. X    (setq entry nil)
  1162. X    ) ; if
  1163. X      ) ; while
  1164. X                    ; return
  1165. X    entry
  1166. X    ) ; let
  1167. X  ) ; defun tpl-mode-match
  1168. X
  1169. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1170. X
  1171. X(defun tpl-mode-name (mode-entry)
  1172. X  "Selector for name field of MODE-ENTRY."
  1173. X                    ; Local Variables
  1174. X  (let ()
  1175. X                    ; Body
  1176. X    (car (cdr (assq 'name mode-entry)))
  1177. X    ) ; let
  1178. X  ) ; defun tpl-mode-name
  1179. X
  1180. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1181. X
  1182. X(defun tpl-mode-templates (mode-entry)
  1183. X  "Selector for templates field of MODE-ENTRY."
  1184. X                    ; Local Variables
  1185. X  (let ()
  1186. X                    ; Body
  1187. X    (car (cdr (assq 'templates mode-entry)))
  1188. X    ) ; let
  1189. X  ) ; defun tpl-mode-templates
  1190. X
  1191. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1192. X
  1193. X(defun tpl-parse-choice (line)
  1194. X  "Break menu LINE into component parts: (string template) or (string nil)."
  1195. X                    ; Local Variables
  1196. X  (let (string-part template-part end-string end-template)
  1197. X                    ; Body
  1198. X                    ; Line = 
  1199. X                    ; "abc" is string "abc"
  1200. X                    ; "abc:" is template "abc"
  1201. X                    ; "abc:def" is template "def"
  1202. X                    ; ";" begins comment area
  1203. X    (setq end-string (string-match tpl-pattern-symbol line))
  1204. X    (setq string-part (substring line 0 (match-end 0)))
  1205. X    (setq line (substring line (match-end 0)))
  1206. X    (setq end-string (string-match "^\\(\\s \\)*:\\(\\s \\)*" line))
  1207. X    (if end-string
  1208. X    (progn
  1209. X      (setq line (substring line (match-end 0)))
  1210. X      (setq end-string (string-match
  1211. X                (concat "^" tpl-pattern-symbol) line))
  1212. X      (if end-string
  1213. X          (setq template-part (substring line 0 (match-end 0)))
  1214. X        ; else
  1215. X        (setq template-part string-part)
  1216. X        ) ; if end-template
  1217. X      ) ; progn
  1218. X      ; else
  1219. X      (progn
  1220. X    (setq template-part nil)
  1221. X    ) ; progn
  1222. X      ) ; if end-string
  1223. X    (list string-part template-part)
  1224. X    ) ; let
  1225. X  ) ; defun tpl-parse-choice
  1226. X
  1227. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1228. X
  1229. X(defun tpl-rebuild-global-template-list (name templates)
  1230. X  "Rebuild global template list, changing major mode NAME to
  1231. X    include TEMPLATES."
  1232. X                    ; Local Variables
  1233. X  (let (mode-list mode-item entry result)
  1234. X                    ; Body
  1235. X    (setq result nil)
  1236. X    (setq entry nil)
  1237. X    (setq mode-list tpl-global-template-list)
  1238. X    (while (and mode-list (not entry))
  1239. X      (setq mode-item (car mode-list))
  1240. X      (setq mode-list (cdr mode-list))
  1241. X      (if (string-equal (tpl-mode-name mode-item) name)
  1242. X      (setq entry mode-item)
  1243. X    ; else
  1244. X    (setq result (append result (list mode-item)))
  1245. X    ) ; if (equal (tpl-mode-name mode-item) name)
  1246. X      ) ; while mode-list
  1247. X    (if (not entry)
  1248. X    (progn
  1249. X      (setq tpl-global-template-list
  1250. X        (append result
  1251. X            (list (tpl-make-template-entry name templates))))
  1252. X      (message "Added templates for %s." name)
  1253. X      ) ; progn
  1254. X      ; else
  1255. X      (if (or (not (tpl-mode-templates mode-item))
  1256. X          (y-or-n-p "Replace existing templates for this mode? "))
  1257. X      (progn
  1258. X        (setq result
  1259. X          (append result (list (tpl-make-template-entry name
  1260. X                                templates))))
  1261. X        (setq result (append result mode-list))
  1262. X        (setq tpl-global-template-list result)
  1263. X        (message "Added templates for %s." name)
  1264. X        ) ; progn
  1265. X    ) ; if
  1266. X      ) ; if
  1267. X    ) ; let
  1268. X  ) ; defun tpl-rebuild-global-template-list
  1269. X
  1270. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1271. X
  1272. X(defun tpl-replace-group (from to)
  1273. X  "Replace current region with a temporary placeholder.
  1274. X    Arguments FROM and TO are ignored.  (They are only needed
  1275. X    for compatibility with other replacement functions.)"
  1276. X                    ; Local Variables
  1277. X  (let (name)
  1278. X                    ; Body
  1279. X    (if tpl-get-placeholder-name-in-context
  1280. X    (setq name nil)
  1281. X      ; else
  1282. X      (progn
  1283. X    (setq name tpl-next-placeholder-name)
  1284. X    (tpl-increment-next-placeholder-name)
  1285. X    ) ; progn
  1286. X      ) ; if tpl-get-placeholder-name-in-context
  1287. X    (replace-region-with-placeholder (mark) (point) name
  1288. X                     "new.tpl" nil)
  1289. X    ) ; let
  1290. X  ) ; defun tpl-replace-group
  1291. X
  1292. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1293. X
  1294. X(defun tpl-replace-line (from to)
  1295. X  "Replace current line with a temporary placeholder.
  1296. X    Arguments FROM and TO are ignored.  (They are only needed
  1297. X    for compatibility with other replacement functions.)"
  1298. X                    ; Local Variables
  1299. X  (let (name)
  1300. X                    ; Body
  1301. X    (if tpl-get-placeholder-name-in-context
  1302. X    (setq name nil)
  1303. X      ; else
  1304. X      (progn
  1305. X    (setq name tpl-next-placeholder-name)
  1306. X    (tpl-increment-next-placeholder-name)
  1307. X    ) ; progn
  1308. X      ) ; if tpl-get-placeholder-name-in-context
  1309. X    (replace-line-with-placeholder 1 name "new.tpl" nil)
  1310. X    ) ; let
  1311. X  ) ; defun tpl-replace-line
  1312. X
  1313. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1314. X
  1315. X(defun tpl-root-of-file-name (file)
  1316. X  "Find the root of FILE as a template file name."
  1317. X                    ; Local Variables
  1318. X  (let (result)
  1319. X                    ; Body
  1320. X    (cond
  1321. X     ((and (> (length file) 7)
  1322. X       (equal (substring file -7) "tpl.elc"))
  1323. X      (setq result (substring file 0 -7))
  1324. X      )
  1325. X     ((and (> (length file) 6)
  1326. X       (equal (substring file -6) "tpl.el"))
  1327. X      (setq result (substring file 0 -6))
  1328. X      )
  1329. X     ((and (> (length file) 4)
  1330. X       (equal (substring file -4) ".tpl"))
  1331. X      (setq result (substring file 0 -4))
  1332. X      )
  1333. X     (t
  1334. X      (setq result file)
  1335. X      )
  1336. X     ) ; cond
  1337. X                    ; return
  1338. X    result
  1339. X    ) ; let
  1340. X  ) ; defun tpl-root-of-file-name
  1341. X
  1342. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1343. X
  1344. X(defun tpl-undo-keymap ()
  1345. X  "Undo keymap for template-mode."
  1346. X                    ; Local Variables
  1347. X  (let ()
  1348. X                    ; Body
  1349. X    (use-local-map tpl-saved-map)
  1350. X    ) ; let
  1351. X  ) ; defun tpl-undo-keymap
  1352. X
  1353. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1354. X
  1355. X(defun tpl-unwrap-template (template &optional arg)
  1356. X  "Find the enclosing TEMPLATE around point and replace it with
  1357. X    whatever is matching the destination placeholder.
  1358. X    Optional second argument non-nil causes mark to be placed
  1359. X    at the beginning of the resulting region."
  1360. X                    ; Local Variables
  1361. X  (let (origin wrapper-pair wrapper-begin wrapper-end indent-amount
  1362. X           prefix another-wrapper-end start match-start
  1363. X           match-stop-marker)
  1364. X                    ; Body
  1365. X    (setq origin (point))
  1366. X    (setq match-stop-marker (make-marker))
  1367. X    (setq wrapper-pair (tpl-find-wrappers template))
  1368. X    (setq wrapper-begin (nth 0 wrapper-pair))
  1369. X    (setq wrapper-end (nth 1 wrapper-pair))
  1370. X    (setq indent-amount (nth 2 wrapper-pair))
  1371. X    (if (search-backward wrapper-begin (point-min) t)
  1372. X    (progn
  1373. X      (setq start (point))
  1374. X      (search-forward wrapper-begin)
  1375. X      (delete-region start (point))
  1376. X      (setq match-start (point))
  1377. X                    ; Get prefix of line for another try
  1378. X                    ;   at matching ending part.
  1379. X      (beginning-of-line nil)
  1380. X      (setq prefix (buffer-substring (point) match-start))
  1381. X      (goto-char match-start)
  1382. X      (setq another-wrapper-end (concat (substring wrapper-end 0 1)
  1383. X                        prefix
  1384. X                        (substring wrapper-end 1)))
  1385. X      ) ; progn
  1386. X      ; else
  1387. X      (error "Enclosing template not found.")
  1388. X      ) ; if
  1389. X    (if (search-forward wrapper-end (point-max) t)
  1390. X    (progn
  1391. X      (setq start (point))
  1392. X      (search-backward wrapper-end (point-min) t)
  1393. X      (delete-region (point) start)
  1394. X      (set-marker match-stop-marker (point))
  1395. X      ) ; progn
  1396. X      ; else
  1397. X                    ; This is a hack to fix indented
  1398. X                    ;   matches.
  1399. X      (if (search-forward another-wrapper-end (point-max) t)
  1400. X      (progn
  1401. X        (setq start (point))
  1402. X        (search-backward another-wrapper-end (point-min) t)
  1403. X        (delete-region (point) start)
  1404. X        (set-marker match-stop-marker (point))
  1405. X        (goto-char match-start)
  1406. X        (delete-backward-char (length prefix))
  1407. X        (setq match-start (- match-start (length prefix)))
  1408. X        ) ; progn
  1409. X    ; else
  1410. X    (progn
  1411. X      (goto-char origin)
  1412. X      (error "End of enclosing template not found.")
  1413. X      ) ; progn
  1414. X    ) ; if ...another...
  1415. X      ) ; if
  1416. X    (goto-char match-start)
  1417. X    (forward-line 1)
  1418. X    (if (< (point) (marker-position match-stop-marker))
  1419. X    (indent-rigidly (point) (marker-position match-stop-marker)
  1420. X            (- 0 indent-amount))
  1421. X      ) ; if
  1422. X    (goto-char (marker-position match-stop-marker))
  1423. X    (set-marker match-stop-marker nil)
  1424. X    (if arg
  1425. X    (push-mark match-start)
  1426. X      ) ; if arg
  1427. X    ) ; let
  1428. X  ) ; defun tpl-unwrap-template
  1429. X
  1430. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1431. X
  1432. X(defun tpl-wrap-template (start stop template)
  1433. X  "Replace the region between START and STOP with TEMPLATE,
  1434. X    reinserting the replaced region at the destination placeholder.
  1435. X    The region is indented rigidly at its insertion column."
  1436. X                    ; Local Variables
  1437. X  (let (save-expand-option region start-column orig-column)
  1438. X                    ; Body
  1439. X    (setq save-expand-option tpl-ask-expansion-depth)
  1440. X    (setq tpl-ask-expansion-depth 0)
  1441. X    (setq region (buffer-substring start stop))
  1442. X    (delete-region start stop)
  1443. X    (goto-char start)
  1444. X    (setq orig-column (current-column))
  1445. X    (unwind-protect            ; Protect against nonexistent template
  1446. X    (tpl-generate template)
  1447. X      (setq start (point))
  1448. X      (setq start-column (current-column))
  1449. X      (insert region)
  1450. X      (indent-rigidly start (point) (- start-column orig-column))
  1451. X      (setq tpl-ask-expansion-depth save-expand-option)
  1452. X      ) ; unwind-protect
  1453. X    (message "Done.")
  1454. X    ) ; let
  1455. X  ) ; defun tpl-wrap-template
  1456. X
  1457. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1458. X
  1459. X(defun tpl-y-or-n-p (msg)
  1460. X  "Display MSG and await positive ('y') or negative ('n') response.
  1461. X    Differs from 'y-or-n-p' in that it leaves the cursor in the active
  1462. X    window, rather than moving to the mode-line."
  1463. X                    ; Local Variables
  1464. X  (let (answered prompt reply result)
  1465. X                    ; Body
  1466. X    (setq answered nil)
  1467. X    (setq prompt (concat msg "(y or n) "))
  1468. X    (while (not answered)
  1469. X      (message prompt)
  1470. X      (setq reply (read-char))
  1471. X      (cond
  1472. X       ((char-equal reply ?y)
  1473. X    (setq answered t)
  1474. X    (setq result t)
  1475. X    ) ; (char-equal reply ?y)
  1476. X       ((char-equal reply ? )
  1477. X    (setq answered t)
  1478. X    (setq result t)
  1479. X    ) ; (char-equal reply ? )
  1480. X       ((char-equal reply ?n)
  1481. X    (setq answered t)
  1482. X    (setq result nil)
  1483. X    ) ; (char-equal reply ?n)
  1484. X       ((char-equal reply ?\177)
  1485. X    (setq answered t)
  1486. X    (setq result nil)
  1487. X    ) ; (char-equal reply ?\177)
  1488. X       (t
  1489. X    (ding)
  1490. X    (setq prompt (concat "Please respond 'y' or 'n'.  "
  1491. X                 msg "(y or n) "))
  1492. X    ) ; t
  1493. X       ) ; cond
  1494. X      ) ; while (not answered)
  1495. X                    ; return
  1496. X    result
  1497. X    ) ; let
  1498. X  ) ; defun tpl-y-or-n-p
  1499. X
  1500. X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1501. X
  1502. X;;; end of tplhelper.el
  1503. SHAR_EOF
  1504. if test 45072 -ne "`wc -c < 'tplhelper.el'`"
  1505. then
  1506.     echo shar: "error transmitting 'tplhelper.el'" '(should have been 45072 characters)'
  1507. fi
  1508. fi
  1509. exit 0
  1510. #    End of shell archive
  1511.  
  1512.  
  1513.